        TTL     > FS30 : Filing system starts here

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

FSAckEscape
        JSR     AckEscape

qFSEscape
        GENAD   mEscape         ; Raise error
        JMP     CauseBRK

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    Y = 0 -> DoBoot

AutoBoot ROUT

 [ $False
        LDAIM   B_KbSc16        ; Doesn't work as such ...
        JSR     osbyte          ; Always says no key pressed
        INX
        BEQ     #FT50

        JMP     EndService
 ]

; Start filing system

50      LDAIM   B_Service
        LDXIM   SV_StartUpFS
        LDYIM   fs_dfs
        JSR     osbyte

        LDAIM   0               ; Read back current fs
        TAY
        JSR     osargs
        CMPIM   fs_dfs
        BEQ     #FT60
        CMPIM   fs_nfs
        BEQ     #FT65
        CMPIM   fs_adfs
        BEQ     #FT70
        CMPIM   fs_arfs
        BEQ     #FT75
        JMP     EndService      ; Something silly has happened

60      JSR     vstring
        =       "Acorn DFS", CR, CR
        NOP
        BRA     #FT80

65      JSR     vstring
        =       "Acorn Econet", CR, CR
        NOP
        BRA     #FT80

70      JSR     vstring
        =       "Acorn ADFS", CR, CR
        NOP
        BRA     #FT80

75      JSR     vstring
        =       "Acorn ARFS", CR, CR
        NOP

80 ; Ignore booting request (Y=0)

        JMP     ClaimService

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    Y = failing situation to start up

StartUpFS ROUT

 [ $debugservice
 LDAIM "Y"
 JSR oswrch
 TYA
 JSR debugA
 ]
        PHY

        CPYIM   fs_dfs          ; No Arthur involvement here
        BEQ     #FT70           ; - stay on current Arthur FS
        CPYIM   fs_arfs
        BEQ     #FT50

        CPYIM   fs_nfs
        BEQ     #FT20
        CPYIM   fs_adfs
        BEQ     #FT20

        PLY
        JMP     EndService      ; Not any of my babies


20      LDAIM   B_Service       ; Tell Arthur to swap filing systems
        LDXIM   SV_StartUpFS
        =       ar_byte


50      JSR     DoStart

        PLY
        STY     currfs          ; Remember you're a womble

        JMP     ClaimService


70      JSR     DFSDoStart

        PLY
        STY     currfs          ; Remember you're a womble

        JMP     ClaimService

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

DoStart ROUT

        LDAIM   FSC_Die         ; Tell current filing system to get stuffed
        JSR     JMI_FSC

        LDAIM   B_Service       ; Claim absolute workspace
        LDXIM   SV_UseStatic
        JSR     osbyte

        LDAIM   B_ExtVectors
        LDXIM   0
        LDYIM   255
        JSR     osbyte          ; YX -> base of extended vector table
        STXY    vstrptr

voffset *       filev-userv     ; Vector number * 2 of our first vector

        LDXIM   voffset
10      LDAIM   &FF             ; Make normal -> extended vector (&FF00 + n*3)
        STAAX   userv+1
        STX     fstmp           ; Make *3
        LSR     fstmp           ; Will give CClear, as X = n*2
        TXA
        ADC     fstmp
        STAAX   userv

        TAY                     ; Set extended vectors up. Y = n*3, X = n*2
        LDAAX   NewVectors-voffset
        STAIY   vstrptr
        INY
        LDAAX   NewVectors-voffset+1
        STAIY   vstrptr
        INY
        LDA     ROMid
        STAIY   vstrptr

        CPXIM   fscv-userv      ; Done the last one ?
        BEQ     #FT90
        INX
        INX
        BRA     #BT10

90      LDAIM   B_Service       ; Inform rest of world of vector change
        LDXIM   SV_Vectors
        JSR     osbyte

 [ $False ; These don't need dynamic space
; Reinitialise our static ws from the dynamic copy

        LDX     ROMid
        LDAAX   RPrivTable
        CLR     pwptr
        STA     pwptr+1

        LDYIM   d_dfsdrive
        LDAIY   pwptr
        STA     dfsdrive
        CLR     dfsdrive+1      ; Ensure terminated
        CLR     tmpdrive+1      ; Ensure terminated

        LDYIM   d_dfsdir
        LDAIY   pwptr
        STA     dfsdir

        LDYIM   d_dfsldrive
        LDAIY   pwptr
        STA     dfsldrive
        CLR     dfsldrive+1     ; Ensure terminated

        LDYIM   d_dfslib
        LDAIY   pwptr
        STA     dfslib
 ]

        RTS


NewVectors
        &       mos_file
        &       mos_args
        &       mos_bget
        &       mos_bput
        &       mos_gbpb
        &       mos_find
        &       mos_fsc

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;         Filing system entry points that we've installed on the vectors
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

mos_args
        CMPIM   0
        BNE     #FT90
        CPYIM   0
        BNE     #FT90
        LDA     currfs
        RTS

90
        =       ar_args
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

mos_bget =      ar_bget
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

mos_bput =      ar_bput
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    YX = cb^

mos_file ROUT

        STXY    cbptr

        CMPIM   &FF
        BEQ     #FA10

        CMPIM   &00
        BEQ     #FT01

        CMPIM   7+1
        BCS     #FT00           ; NOP unknown reason codes
        =       ar_file

00      RTS

01      JMP     #FA50


qNotFound
        GENAD   mNotFound
        JMP     CauseBRK

mNotFound
        =       &D6
        =       "Not found", 0


qNotFile ; A = type
        CMPIM   2               ; Was it a dir ?
        BNE     qNotFound


qIsADir GENAD   mIsADir
        JMP     CauseBRK

mIsADir =       &A8
        =       "Is a directory", 0


10 ; LOAD: Mutate into reads of n bytes a go, poke ourselves

        LDYIM   17              ; Copy user cb to our space
11      LDAIY   cbptr
        STAAY   fil_blk
        DEY
        BPL     #BT11

        LDA     fil_exec        ; Load at own ?
        PHA                     ; Remember for later

        LDXY    cbptr
        LDAIM   5               ; Read file info into user cb
        =       ar_file
        CMPIM   1
        BNE     qNotFile

        LDXY    fil_load        ; Where user initially said to put it
        PLA
        BEQ     #FA15           ; [load at given]

        LDYIM   2
        LDAIY   cbptr           ; Read load address of file from info
        TAX
        INY
        LDAIY   cbptr
        TAY

15      STXY    osf_load        ; Create zp^ for copy

        LDXY    fil_name
        LDAIM   &40             ; OpenIn
        =       ar_find
        STA     gbpb_handle

20      CLR     gbpb_nbytes+0
        LDAIM   1
        STA     gbpb_nbytes+1
        CLR     gbpb_nbytes+2
        CLR     gbpb_nbytes+3

        GENAD   osf_buffer
        STXY    gbpb_addr
        LDAIM   &FF             ; Pedantically set Host addresses
        STA     gbpb_addr+2
        STA     gbpb_addr+3

        LDAIM   4               ; Read from current seqptr
        GENAD   gbpb_blk
        =       ar_gbpb
        LDA     gbpb_nbytes+1
        CMPIM   1               ; No bytes read ?
        BEQ     #FT80

        LDYIM   0
25      LDAAY   osf_buffer
        STAIY   osf_load
        INY
        INC     gbpb_nbytes
        BNE     #BT25
        INC     osf_load+1

        TYA                     ; Was that the last chunk ?
        BEQ     #BT20           ; [no, loop]

80      LDAIM   0               ; Close file
        LDY     gbpb_handle
        =       ar_find

        LDXY    cbptr           ; Preserve YX
        LDAIM   1               ; Was a file (must have been)
        RTS



50 ; SAVE: peek blocks and output them

        LDYIM   17              ; Copy user cb to our space
55      LDAIY   cbptr
        STAAY   fil_blk
        DEY
        BPL     #BT55

        LDXY    cbptr
        LDAIM   7               ; Create right size file
        =       ar_file

        LDXY    fil_start       ; Create zp^ for copy
        STXY    osf_save

        LDXY    fil_name
        LDAIM   &C0             ; OpenUp
        =       ar_find
        STA     gbpb_handle
        TAY

60      LDAI    osf_save
        =       ar_bput
        INC     osf_save
        BNE     #FT70
        INC     osf_save+1

70      LDA     osf_save
        CMP     fil_end
        BNE     #BT60
        LDA     osf_save+1
        CMP     fil_end+1
        BNE     #BT60

        LDAIM   0               ; Close file
        LDY     gbpb_handle
        =       ar_find

        LDXY    cbptr
        LDAIM   2               ; Write right load, exec. FileSwitch doesn't
        =       ar_file         ; corrupt the cb 'cos I knows this
        LDAIM   3               ; Can't write attributes though, so use 2 ops
        =       ar_file

;***^   LDXY    cbptr           ; Preserve YX
        LDAIM   0               ; Was a save op
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

mos_find
        ANDIM   &C0             ; Only look at top two bits
        =       ar_find
        ORAIM   &00             ; I have known programs look at Z after this!
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; No emulation added; I've never seen anyone GBPB to the screen ram

; Only purists like Nosbod would complain about this one !

mos_gbpb ROUT

        CMPIM   8+1             ; NOP unknown reason codes
        BCS     #FT99

        =       ar_gbpb

99      RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    A = reason code
;       X, Y parms

mos_fsc ROUT

        CMPIM   FSC_Enable +1   ; NOP unknown FSC calls
        BCS     #FT99

        STX     fstmp
        ASLA
        TAX
        LDAAX   fscrouts+1      ; MSB
        PHA
        LDAAX   fscrouts        ; LSB
        PHA
        LDX     fstmp

99      RTS

fscrouts
        &       FSOpt - 1
        &       FSEof - 1
        &       FSRun - 1
        &       FSCommand - 1
        &       FSRun - 1
        &       FSCat - 1
        &       FSDie - 1
        &       FSHanRange - 1
        &       FSEnable - 1

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Curl up and die

FSDie   JSR     GetPWptr

 [ $False
; Copy away useful information

        LDA     dfsdrive
        LDYIM   d_dfsdrive
        STAIY   pwptr

        LDA     dfsdir
        LDYIM   d_dfsdir
        STAIY   pwptr

        LDA     dfsldrive
        LDYIM   d_dfsldrive
        STAIY   pwptr

        LDA     dfslib
        LDYIM   d_dfslib
        STAIY   pwptr
 ]

        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

GetPWptr ROUT

        PHX
        PHA
        LDX     ROMid
        LDAAX   RPrivTable
        CLR     pwptr
        STA     pwptr+1
        PLA
        PLX
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Can't opt as yet

FSOpt   RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

FSEof   ROUT

        LDAIM   5               ; New Arthur op
        =       ar_args
        TXA
        BEQ     #FT99
        LDXIM   &FF             ; Ensure consistency
99      RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    YX -> command

CallerBits
        =       0, 0, 0, 0, dfs_cmd, nfs_cmd, 0, 0, adfs_cmd, 0, 0, arfs_cmd
;               0  1  2  3     4        5     6  7      8     9 10     11

FSCommand ; NOROUT
 [ $debugfs
 JSR vstring
 = "fsc "
 NOP
 ]
        PHX
        LDX     currfs          ; From FSCommand/FileSystem n
        LDAAX   CallerBits
        PLX
        JSR     Decode
        BCC     #BT99           ; Exit if processed

        LDXY    cliptr

; .............................................................................
; In    YX -> command

FSRun   ROUT
 [ $debugfs
 JSR vstring
 = "run"
 NOP
 ]
        STXY    fil_name

        GENAD   fil_blk         ; Exists ?
        LDAIM   5
        =       ar_file
        DECA                    ; File ?
        BNE     #FT99           ; 'Bad command'

        LDX     fil_exec
        LDY     fil_exec+1
        TXA
        AND     fil_exec+1      ; Has it an exec address of &FFFFFFFF?
        AND     fil_exec+2
        AND     fil_exec+3
        CMPIM   &FF
        BEQ     #FT50           ; [yup]

        PHX                     ; Save exec address
        PHY

        LDAIM   &FF
        STA     fil_exec        ; Load at own
        GENAD   fil_blk
        JSR     mos_file        ; Can't use ar_file

        PLY                     ; Restore exec address
        PLX

        JMP     StartCodeXY     ; If that returns, does RTS to caller


50      LDAIM   &40             ; Open for input
        LDXY    fil_name
        =       ar_find
        TAX
        BEQ     #FT99           ; [waargh]

        LDAIM   198             ; Read old EXEC handle/write new one
        LDYIM   0
        JSR     osbyte
        TXA
        BEQ     #FT80           ; [no old EXEC handle]

        TAY                     ; Close old EXEC file
        LDAIM   0
        =       ar_find

80      RTS


99      JMP     qBadCommand

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Handle range request. No translation done by arfs

FSHanRange
        LDXIM   1
        LDYIM   254
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Don't give a toss about ..

FSEnable
        RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    YX -> dir to cat (see also *ex code)

FSCat ROUT

        LDA     currfs
        CMPIM   fs_dfs
        BEQ     #FT00
        JMP     #FA05

00      LDA     dfsdir
        STA     tmpdir
        LDA     dfsdrive
        STA     tmpdrive

        STXY    fscptr
        LDYIM   0
        LDAIY   fscptr
        CMPIM   space
        BCC     #FT03           ; [no arg, use current drive and dir]

        CMPIM   ":"
        BNE     #FT02           ; [no drive spec]

        INY
        LDAIY   fscptr
        JSR     chkdrive
        STA     tmpdrive

        INY
        LDAIY   fscptr
        CMPIM   space
        BCC     #FT03           ; [just drive specified, use current dir]
        JSR     chkdot

        INY
        LDAIY   fscptr

02      JSR     chkdir
        STA     tmpdir

03      LDA     tmpdir          ; Build 'f*' to match
        JSR     mkarfchar
        STA     dfsname
        LDAIM   "*"
        STA     dfsname+1
        CLR     dfsname+2

        JSR     vstring
        =       "Drive "
        NOP
        LDA     tmpdrive
        JSR     oswrch
        JSR     osnewl

        JSR     vstring
        =       "Dir. :"
        NOP
        LDA     dfsdrive
        JSR     oswrch
        LDAIM   "."
        JSR     oswrch
        LDA     dfsdir
        JSR     oswrch

        JSR     vstring
        =       "            Lib. :"
        NOP
        LDA     dfsldrive
        JSR     oswrch
        LDAIM   "."
        JSR     oswrch
        LDA     dfslib
        JSR     oswrch

        JSR     osnewl          ; DFS gives lots of blank lines!

        GENAD   tmpdrive        ; Examine this directory for DFS files
        STXY    gbpb_dirname    ; Never updated

; ***^  GENAD   tmpdrive        ; Check the 'drive' exists first
        STXY    fil_name
        LDAIM   5               ; OSFile_ReadInfo
        GENAD   fil_blk
        =       ar_file
        CMPIM   2
        BEQ     #FA04

        JMP     qBadDrive

04      GENAD   allwild         ; Always catalogue ALL the files!
        LDAIM   2               ; DFS catalogues are always 2 column
        BRA     #FT09


; Non-DFS *EX

05      STXY    gbpb_dirname    ; Never updated

        JSR     vstring
        =       "Dir. "
        NOP
        LDXY    gbpb_dirname
        JSR     xystring

        SEC
        LDA     &30A            ; RHWind
        SBC     &308            ; RHWind-LHWind
        TAX
        LDAIM   4               ; 4 cols by default
        CPXIM   4*19
        BCS     #FA08
        LDAIM   2
        CPXIM   2*19
        BCS     #FA08
        DECA

08      GENAD   allwild


09      STA     ncolumns
        STA     tcolumns

        STXY    gbpb_wildpat    ; Never updated

; gbpb_handle unused

        CLR     gbpb_seqptr     ; Start at entry 0
        CLR     gbpb_seqptr+1
        CLR     gbpb_seqptr+2
        CLR     gbpb_seqptr+3

        CLR     gbpb_nbytes+1   ; Never modified away from 0
        CLR     gbpb_nbytes+2
        CLR     gbpb_nbytes+3

        LDAIM   &FF             ; Pedantically set Host addresses
        STA     gbpb_dirname+2
        STA     gbpb_dirname+3
        STA     gbpb_wildpat+2
        STA     gbpb_wildpat+3

        JSR     osnewl
        JSR     osnewl


10 ; Loop till bored

        LDA     escflag
        BMI     #FT95

        GENAD   gbpb_catblk
        STXY    gbpb_addr
        LDAIM   &FF             ; Pedantically set Host addresses
        STA     gbpb_addr+2
        STA     gbpb_addr+3

        LDAIM   1
        STA     gbpb_nbytes

        LDAIM   10              ; OSGBPB_ReadDirEntriesInfo
        GENAD   gbpb_blk
        =       ar_gbpb

        LDA     gbpb_nbytes
        BEQ     #FT40           ; [no name matched]

        LDA     currfs
        CMPIM   fs_dfs
        BNE     #FT20

        LDA     gbpb_objtype    ; Don't print out DFS directories
        DECA
        BNE     #FT40           ; [is a dir, don't count as object]

        JSR     CatPrintDFS
        BRA     #FT30

; Simple non-DFS case

20      LDAIM   19              ; Field width
        GENAD   gbpb_retname
        JSR     XYfilename      ; and return

30      DEC     tcolumns
        BNE     #FT40           ; [more objects printable]

        LDX     ncolumns        ; Reset column count
        STX     tcolumns
        JSR     osnewl          ; and go newline

40      LDA     gbpb_seqptr+3
        BPL     #BT10           ; [not yet ended dir read]


90      LDX     ncolumns
        CPX     tcolumns
        BEQ     #FT99           ; [already at newline]

        JSR     osnewl

99      RTS


95      JMP     FSAckEscape


allwild =       "*", 0          ; Match all filenames returned

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; In    YX -> filename to print in field of A bytes, truncating as needed

; Out   vstrptr,Y,X,A corrupt

XYfilename ROUT

        STXY    vstrptr

        TAX                     ; Print name in field of A, rj with spaces
        LDYIM   0

20      DEX
        BMI     #FT90

        LDAIY   vstrptr
        CMPIM   space
        BCC     #FT30
        INY

25      JSR     oswrch
        BRA     #BT20           ; Loop

30      LDAIM   space
        BRA     #BT25

90      RTS

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

JMI_FSC JMI     fscv

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        LNK     FS35
